﻿using Microsoft.AspNetCore.Http;
using System;
using Urs.Core;
using Urs.Data.Domain.Users;
using Urs.Services.Authentication;
using Urs.Services.Users;

namespace Urs.Framework
{
    /// <summary>
    /// Working context for web application
    /// </summary>
    public partial class WebWorkContext : IWorkContext
    {
        private const string UserCookieName = "Urs.user";

        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IUserService _userService;
        private readonly IAuthenticationService _authenticationService;
        private readonly IWebHelper _webHelper;
        private User _cachedUser;

        public WebWorkContext(IHttpContextAccessor httpContextAccessor,
            IUserService userService,
            IAuthenticationService authenticationService,
            IWebHelper webHelper)
        {
            this._httpContextAccessor = httpContextAccessor;
            this._userService = userService;
            this._authenticationService = authenticationService;
            this._webHelper = webHelper;
        }

        protected User GetCurrentUser()
        {
            if (_cachedUser != null)
                return _cachedUser;

            User user = null;
            if (_httpContextAccessor != null)
            {
                //registered user
                if (user == null || user.Deleted || !user.Active)
                {
                   user = _authenticationService.GetAuthenticatedUser();
                }

                //load guest user
                if (user == null || user.Deleted)
                {
                    var userCookie = GetUserCookie();
                    if (!String.IsNullOrEmpty(userCookie))
                    {
                        if (Guid.TryParse(userCookie, out Guid userGuid))
                        {
                            var userByCookie = _userService.GetUserByGuid(userGuid);
                            if (userByCookie != null &&
                                //this user (from cookie) should not be registered
                                !userByCookie.IsRegistered())
                                user = userByCookie;
                        }
                    }
                }

                //create guest if not exists
                if (user == null || user.Deleted)
                {
                    user = _userService.InsertGuestUser();
                }

                SetUserCookie(user.UserGuid);
            }

            //validation
            if (user != null && !user.Deleted)
            {

                _cachedUser = user;
            }

            return _cachedUser;
        }

        protected string GetUserCookie()
        {
            return _httpContextAccessor.HttpContext?.Request?.Cookies[UserCookieName];
        }

        protected void SetUserCookie(Guid userGuid)
        {
            if (_httpContextAccessor.HttpContext?.Response == null)
                return;

            _httpContextAccessor.HttpContext.Response.Cookies.Delete(UserCookieName);

            //get date of cookie expiration
            var cookieExpires = 24 * 365; //TODO make configurable
            var cookieExpiresDate = DateTime.Now.AddHours(cookieExpires);

            //if passed guid is empty set cookie as expired
            if (userGuid == Guid.Empty)
                cookieExpiresDate = DateTime.Now.AddMonths(-1);

            //set new cookie value
            var options = new CookieOptions
            {
                HttpOnly = true,
                Expires = cookieExpiresDate
            };
            _httpContextAccessor.HttpContext.Response.Cookies.Append(UserCookieName, userGuid.ToString(), options);
        }

        /// <summary>
        /// Gets or sets the current user
        /// </summary>
        public User CurrentUser
        {
            get
            {
                return GetCurrentUser();
            }
            set
            {
                SetUserCookie(value.UserGuid);
                _cachedUser = value;
            }
        }
    }
}
